package singleton;

import org.junit.jupiter.api.Test;
import singleton.HungryType;
import singleton.InnerClassType;
import singleton.LazyType;

import java.lang.reflect.Constructor;

public class TestFile {

    //获得两次对象的地址相同，说明饿汉式单例有效
    @Test
    public void testHungryType1(){
        HungryType hungryType1 = HungryType.getHungryType();
        HungryType hungryType2 = HungryType.getHungryType();
        System.out.println(hungryType1);
        System.out.println(hungryType2);
    }

    //懒汉式单例有效，但线程不安全
    @Test
    public void testLazyType(){
        LazyType lazyType1 = LazyType.getLazyType();
        LazyType lazyType2 = LazyType.getLazyType();
        System.out.println(lazyType1);
        System.out.println(lazyType2);
    }

    //懒汉式多线程测试，结果为不安全的
    @Test
    public void testLazyType2(){
        for (int i = 0; i < 9; i++) {
            new Thread(()->{
//                try {
//                    Thread.sleep(10);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                LazyType.getLazyType();
            }).start();
        }
    }

    //构造器加锁验证依然不能阻止反射的破坏
    //设立一个旗标位来保证连续两次使用反射创建对象造成的不安全问题
    @Test
    public void testLazyType3() throws Exception {
//        LazyType lazyType3 = LazyType.getLazyType();
        Constructor<LazyType> declaredConstructor =
                LazyType.class.getDeclaredConstructor(null);
        declaredConstructor.setAccessible(true);
        LazyType lazyType1 = declaredConstructor.newInstance();
        LazyType lazyType2 = declaredConstructor.newInstance();

//        System.out.println(lazyType3);
        System.out.println(lazyType1);
        System.out.println(lazyType2);
    }

    //对单例模式静态内部类写法的测试
    @Test
    public void testInnerClassType(){
        InnerClassType innerClassType1 = InnerClassType.getInnerClassType();
        InnerClassType innerClassType2 = InnerClassType.getInnerClassType();

        System.out.println(innerClassType1);
        System.out.println(innerClassType2);
    }

    //反射可以破坏单例模式，所以可以给构造器加锁并进行再次验证
    @Test
    public void testInnerClassType2() throws Exception {
//        InnerClassType innerClassType1 = InnerClassType.getInnerClassType();
        Constructor<InnerClassType> declaredConstructor =
                    InnerClassType.class.getDeclaredConstructor(null);
        declaredConstructor.setAccessible(true);
        InnerClassType innerClassType2 = declaredConstructor.newInstance();
        InnerClassType innerClassType3 = declaredConstructor.newInstance();

//        System.out.println(innerClassType1);
        System.out.println(innerClassType2);
        System.out.println(innerClassType3);
    }















}
